使用RxSwift更好地处理授权提示
把用户授权结果变成一个 Observable
由于 iOS 的用户授权动作是异步的, 因此在请求授权的同时已经在加载资源了, 所以会造成通过授权但是会启动白屏现象; 为了能在用户完成授权操作之后继续更新UI,我们得先把授权的结果封装成一个Observable。
实际上用户授权结果只有两种情况:
- 如果用户已经授权, 事件序列就是:
.next(true)
,.completed()
; - 如果用户未授权,序列的第一个事件就一定是
.next(false)
。然后,如果用户拒绝授权,序列中的事件就是:.next(false)
和.completed
。否则,就是.next(true)
和.completed
;
有了上面的思路, 就可以给 PHPhotoLibrary 添加一个 extension:
|
上面的代码用到了PHPhotoLibrary
的两个 API:
authorizationStatus
获取当前授权状态;requestAuthorization
申请用户授权;
不过有一个需要注意的地方需要是需要把通知observer
的代码放进DispatchQueue.main.async
中; 这是是为了避免在自定义的事件序列中影响其它Observable的订阅,甚至是把整个UI卡住。
订阅用户授权结果
订阅的部分, 应该写在你要请求授权的 ViewController 中的viewDidLoad
方法中, 但是我们并不能直接订阅isAuthorized
的onNext
然后处理 true 和 false 的情况, 因为单一的时间并不能反应授权的情况, 他有以下两种情况:
- 授权成功的序列可能是:
.next(true)
,.completed
或.next(false)
,.next(true)
,.completed
; - 授权失败的序列是:
.next(false)
,.next(false)
,.completed
订阅请求授权成功事件
从上面的分析可以得出, 要订阅授权成功的事件, 我们只需要忽略事件序列中的false
, 然后读取到第一个true
就可以判断授权成功了; 可以使用一个过滤型的时间处理来完成上面的工作:
|
注意上面的处理 UI 的动作也需要在主线程中执行
不过,实际上,我们并不经常在RxSwift的订阅代码里使用GCD,RxSwift提供了一个更简单的机制,叫做scheduler, 我们可以把上面的事件订阅的代码修改成:
|
.observeOn(MainScheduler.instance)
就是表示在主线程中执行订阅代码;
订阅授权失败事件
由于授权失败只有一种情况就是: .next(false)
,.next(false)
,.completed
, 所以可以对事件序列中的所有元素去重, 然后订阅最后一个next事件, 如果是false
, 就表示授权失败了:
|